package config

import (
	_ "embed"
	"os"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

var config = new(Config)

type Config struct {
	APP        APP        `mapstructure:"app"`
	Mysql      Mysql      `mapstructure:"mysql"`
	Redis      Redis      `mapstructure:"redis"`
	Log        Log        `mapstructure:"log"`
	HTTPServer HTTPServer `mapstructure:"httpServer"`
	FilePath   FilePath   `mapstructure:"filePath"`
	Minio      Minio      `mapstructure:"minio"`
	RpcXServer RpcXServer `mapstructure:"rpcServer"`
}

type APP struct {
	Name    string `mapstructure:"name"`
	Version string `mapstructure:"version"`
	Env     string `mapstructure:"env"`
}

type Mysql struct {
	User            string        `mapstructure:"user"`
	Password        string        `mapstructure:"password"`
	Addr            string        `mapstructure:"addr"`
	Port            int           `mapstructure:"port"`
	Database        string        `mapstructure:"database"`
	MaxOpenConn     int           `mapstructure:"maxOpenConn"`
	MaxIdleConn     int           `mapstructure:"maxIdleConn"`
	ConnMaxLifeTime time.Duration `mapstructure:"connMaxLifeTime"`
	LogLevel        int           `mapstructure:"logLevel"`
}

type Redis struct {
	Addr       string `mapstructure:"addr"`
	Port       int    `mapstructure:"port"`
	Db         int    `mapstructure:"db"`
	MaxReTries int    `mapstructure:"maxRetries"`
	Password   string `mapstructure:"password"`
	PoolSize   int    `mapstructure:"poolSize"`
}

type Log struct {
	Level       string      `mapstructure:"level"`
	Stdout      bool        `mapstructure:"stdout"`
	LogRate     bool        `mapstructure:"logRate"`
	LogRateConf LogRateConf `mapstructure:"logRateConf"`
}

type LogRateConf struct {
	MaxAge     int  `mapstructure:"maxAge"`
	MaxBackups uint `mapstructure:"maxBackups"`
	MaxSize    uint `mapstructure:"maxSize"`
}

type HTTPServer struct {
	Address   string `mapstructure:"address"`
	Port      int    `mapstructure:"port"`
	Mode      string `mapstructure:"mode"`
	MachineIp string `mapstructure:"machineIp"`
}

type FilePath struct {
	AgentRootPath  string `mapstructure:"agentRootPath"`
	MountPath      string `mapstructure:"mountPath"`
	MountSubPath   string `mapstructure:"mountSubPath"`
	KubeConfigPath string `mapstructure:"kubeConfigPath"`
}

type Minio struct {
	Host      string `mapstructure:"host"`
	AccessKey string `mapstructure:"accessKey"`
	Secret    string `mapstructure:"secret"`
}

type RpcXServer struct {
	ServerName          string   `mapstructure:"serverName"`
	Address             string   `mapstructure:"address"`
	Port                int      `mapstructure:"port"`
	ReadTimeout         int64    `mapstructure:"readTimeout"`  // 单位秒
	WriteTimeout        int64    `mapstructure:"writeTimeout"` // 单位秒
	EtcdNodes           []string `mapstructure:"etcdNodes"`
	EtcdBasePath        string   `mapstructure:"etcdBasePath"`
	EtcdUpdateInterval  int64    `mapstructure:"etcdUpdateInterval"` // 单位秒
	EtcdExpired         int64    `mapstructure:"etcdExpired"`        // 单位秒
	PondPoolMaxWorkers  int      `mapstructure:"pondPoolMaxWorkers"` // 协程配置，和pondPoolMaxCapacity必须都有值才生效
	PondPoolMaxCapacity int      `mapstructure:"pondPoolMaxCapacity"`
	CertFile            string   `mapstructure:"certFile"`
	KeyFile             string   `mapstructure:"keyFile"`
}

func InitConfig(configName string, configPath string) {

	viper.SetConfigType("yaml")
	viper.SetConfigName(configName)
	viper.AddConfigPath(configPath)

	if err := viper.ReadInConfig(); err != nil {
		panic(err)
	}
	viper.Set("machineIp", os.Getenv("machineIp"))

	if err := viper.Unmarshal(config); err != nil {
		panic(err)
	}

	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		if err := viper.Unmarshal(config); err != nil {
			panic(err)
		}
	})
}

func Get() Config {
	return *config
}
